There is the data: atp_tennis containing the following columns: ['Tournament', 'Date', 'Series', 'Court', 'Surface', 'Round', 'Best of', 'Player_1', 'Player_2', 'Winner', 'Rank_1', 'Rank_2', 'Pts_1', 'Pts_2', 'Odd_1', 'Odd_2', 'score'].  
--- The description for each column this data is:
Tournament: Name of the tennis tournament (Brisbane International, Chennai Open, Qatar Exxon Mobil Open ...etc)
Date: Date the match was played (year-month-day)
Series: Category or level of the tennis tournament (ATP250, ATP500, Masters1000 and Grand Slams offer 250, 500, 1000, and 2000 ranking points to the winner seperately.)
Court: Place the match was held (Indoors or Outdoors)
Surface: Type of court surface (Hard, Grass and Clay)
Round: Stage of the tournament (1st Round, 2nd Round, Quarterfinals, Semifinal and The Final)
Best of: Tourament systems ("best of 3" or "best of 5")
Player_1: Name of the first competitor in each match
Player_2: Name of the second competitor in each match
Winner: Name of the Player_1 or Player_2 who won the match 
Rank_1: World rankings of the Player_1 at the time of the match
Rank_2: World rankings of the Player_2 at the time of the match
Pts_1: Ranking points held by Player_1 before the match (accumulated over the season and higher points typically indicate a more successful player)
Pts_2: Ranking points held by Player_2 before the match
Odd_1: Betting odds for Player_1 (reflecting their perceived chances of winning)
Odd_2: Betting odds for Player_2 
Score: Final score of the match ("score of Player_1" - "score of Player_2")
---
Considering contents from the dataset and requirements from user. Please note DO NOT CHANGE FILE AND VARIABLE NAMES THAT I HAVE SET!
Interactions begin:
[USER (data scientist)]: Can you help me find the matches in the atp_tennis dataset where Roger Federer is either Player_1 or Player_2? I would like to have a list of Match IDs for these matches. Please generate and display a list of match indices involving the player 'Federer R.' in the ATP tennis dataset.

[YOU (AI assistant)]: Sure, I can help you with that. To find the matches where Roger Federer is either Player_1 or Player_2, you can use the following code :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

federer_matches = atp_tennis[(atp_tennis['Player_1'] == 'Federer R.') | (atp_tennis['Player_2'] == 'Federer R.')]
federer_match_ids = federer_matches.index.tolist()

print(federer_match_ids)

'''

[USER (data scientist)]: Hey, I have a dataset of ATP tennis matches in a CSV file called "atp_tennis.csv". I'd like to analyze the performance of a player named "Raonic M." against all opponents that Roger Federer has faced. Can you help me with that? 

[YOU (AI assistant)]: Sure! First, let's load the dataset using pandas. Do you have pandas installed? 

[USER (data scientist)]: Yes, I have pandas installed. 

[YOU (AI assistant)]: Great! Let's start by importing pandas and loading the dataset: 
'''
import pandas as pd

# Load the dataset 
atp_tennis = pd.read_csv("atp_tennis.csv") 
'''
[USER (data scientist)]: Awesome! Now, can you find all the matches where Federer has played? Please generate and display a list of unique opponents who have played against 'Federer R.' in the ATP tennis dataset.

[YOU (AI assistant)]: Sure, let's filter the dataset to find all the matches where Federer is either Player_1 or Player_2 :
'''
import pandas as pd
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

federer_matches = atp_tennis[(atp_tennis['Player_1'] == 'Federer R.') | (atp_tennis['Player_2'] == 'Federer R.')]   
federer_opponents = federer_matches['Player_1'].where(federer_matches['Player_1'] != 'Federer R.', federer_matches['Player_2']).unique()   

print(federer_opponents)

'''

[USER (data scientist)]: Great! Now, can you calculate the surface performance of Raonic M. against each of Federer's opponents? Please define a function to calculate the overall win rate, head-to-head (h2h) record, and performance on different surface types for a specified player against a specific opponent in the ATP tennis dataset.

[YOU (AI assistant)]: Sure, let's modify the existing function to include surface performance calculation :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

def calculate_performance(player, opponent, data, surface_types):   
    player_matches = data[((data['Player_1'] == player) & (data['Player_2'] == opponent)) | ((data['Player_1'] == opponent) & (data['Player_2'] == player))]   
    total_matches = len(player_matches)   
    wins = len(player_matches[player_matches['Winner'] == player])   
    win_rate = wins / total_matches if total_matches > 0 else 0   
    h2h_record = wins / total_matches if total_matches > 0 else 0   

    surface_performance = {}   
    for surface in surface_types:   
        player_surface_matches = player_matches[player_matches['Surface'] == surface]   
        player_surface_wins = len(player_surface_matches[player_surface_matches['Winner'] == player])   
        surface_performance[surface] = player_surface_wins / player_surface_matches.shape[0] if player_surface_matches.shape[0] > 0 else 0   

    return win_rate, h2h_record, surface_performance   

'''

[USER (data scientist)]: That's a nice function! Now, let's create a dataframe to store the results and loop through Federer's opponents to calculate the performance of Raonic M. Please generate and display a DataFrame containing win rate, head-to-head records, and surface performance of 'Raonic M.' against each of his opponents in the ATP tennis dataset.

[YOU (AI assistant)]: Sure, let's initialize an empty dataframe with the required columns and loop through Federer's opponents to calculate the performance :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

# Retrieve unique surface types
surface_types = atp_tennis['Surface'].unique()

# Initialize an empty dataframe for storing the results   
columns = ['Player', 'Opponent', 'Win Rate', 'Head-to-Head'] + [f'{surface} Surface Performance' for surface in surface_types]   
player_stats = pd.DataFrame(columns=columns)   

# Loop through Federer's opponents   
for opponent in federer_opponents:   
    # Calculate win rate, head-to-head record, and surface performance for Raonic M. against each opponent   
    win_rate, h2h_record, surface_performance = calculate_performance('Raonic M.', opponent, atp_tennis, surface_types)   

    # Append the results to the dataframe   
    row_data = {'Player': 'Raonic M.', 'Opponent': opponent, 'Win Rate': win_rate, 'Head-to-Head': h2h_record}   
    row_data.update({f'{surface} Surface Performance': surface_performance[surface] for surface in surface_types})   
    player_stats = pd.concat([player_stats, pd.DataFrame(row_data, index=[0])], ignore_index=True)   

# Display the resulting dataframe   
print(player_stats)

'''

[USER (data scientist)]: Hey Tapilot, I have this dataset of tennis matches, and I want to update the odds for each match based on the new competitors' performance. Can you help me figure out the head-to-head win rates for each player? Please define a function to calculate the head-to-head win rates for all unique player pairings in the ATP tennis dataset.

[YOU (AI assistant)]: Absolutely! Here's a function that calculates the head-to-head win rates for each player in your dataset :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

def calculate_head_to_head_win_rate(data):  
    unique_players = pd.concat([data['Player_1'], data['Player_2']]).unique()  
  
    total_matches = data.groupby(['Player_1', 'Player_2']).size().reset_index().rename(columns={0: 'count_total'})  
    player_wins = data[data['Winner'] == data['Player_1']].groupby(['Player_1', 'Player_2']).size().reset_index().rename(columns={0: 'count_wins'})  
  
    all_pairs = pd.MultiIndex.from_product([unique_players, unique_players], names=['Player', 'Opponent']).to_frame(index=False)  
    all_pairs = all_pairs[all_pairs['Player'] != all_pairs['Opponent']]  
      
    h2h_win_rates = all_pairs.merge(total_matches, left_on=['Player', 'Opponent'], right_on=['Player_1', 'Player_2'], how='left').drop(columns=['Player_1', 'Player_2'])  
    h2h_win_rates = h2h_win_rates.merge(player_wins, left_on=['Player', 'Opponent'], right_on=['Player_1', 'Player_2'], how='left').drop(columns=['Player_1', 'Player_2'])  
  
    h2h_win_rates['count_wins'].fillna(0, inplace=True)  
    h2h_win_rates['count_total'].fillna(1, inplace=True)  
    h2h_win_rates['Head-to-Head Win Rate'] = h2h_win_rates['count_wins'] / h2h_win_rates['count_total']  
  
    h2h_win_rates.drop(columns=['count_total', 'count_wins'], inplace=True)  
  
    return h2h_win_rates   

'''

[USER (data scientist)]: Awesome! Now, I'd like to estimate the probabilities using player performance and head-to-head records, with a 70% weight for the new competitor's win rate. Please define a function to estimate the probability of winning for two players in a tennis match, based on their individual win rates, head-to-head win rates, and specified weights for overall performance and head-to-head results.

[YOU (AI assistant)]: Sure thing! Here's a function that does just that, taking into account the performance and head-to-head weights :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

def estimate_probability(player_1_win_rate, player_2_win_rate, h2h_player_1_win_rate, h2h_player_2_win_rate, performance_weight=0.7, h2h_weight=0.3):  
    if player_1_win_rate + player_2_win_rate == 0:  
        player_1_win_rate = player_2_win_rate = 0.5  
  
    if h2h_player_1_win_rate + h2h_player_2_win_rate == 0:  
        h2h_player_1_win_rate = h2h_player_2_win_rate = 0.5  
  
    weighted_player_1_win_rate = performance_weight * player_1_win_rate + h2h_weight * h2h_player_1_win_rate  
    weighted_player_2_win_rate = performance_weight * player_2_win_rate + h2h_weight * h2h_player_2_win_rate  
    total_weighted_win_rate = weighted_player_1_win_rate + weighted_player_2_win_rate  
  
    player_1_probability = weighted_player_1_win_rate / total_weighted_win_rate  
    player_2_probability = weighted_player_2_win_rate / total_weighted_win_rate  
  
    return player_1_probability, player_2_probability  

'''

[USER (data scientist)]: Great! Now, can you help me create a function to update the odds for each match using these weights? Please define a function to update the odds for each match in the ATP tennis dataset, based on players' overall win rates, head-to-head win rates, and specified weights for performance and head-to-head results.

[YOU (AI assistant)]: Of course! Here's a function that updates the odds for a given match based on the performance and head-to-head weights :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

# Function to update odds based on performance weight and head-to-head weight  
def update_odds(match_id, performance_weight, h2h_weight, data, h2h_win_rates):  
    match = data.loc[match_id]  
    player_1 = match['Player_1']  
    player_2 = match['Player_2']  
  
    player_1_win_rate = player_stats.loc[player_stats['Opponent'] == player_1, 'Win Rate']  
    player_2_win_rate = player_stats.loc[player_stats['Opponent'] == player_2, 'Win Rate']  
  
    player_1_win_rate = player_1_win_rate.iloc[0] if not player_1_win_rate.empty else 0  
    player_2_win_rate = player_2_win_rate.iloc[0] if not player_2_win_rate.empty else 0  
  
    h2h_player_1_win_rate = h2h_win_rates.loc[h2h_win_rates['Opponent'] == player_2, 'Head-to-Head Win Rate']  
    h2h_player_2_win_rate = h2h_win_rates.loc[h2h_win_rates['Opponent'] == player_1, 'Head-to-Head Win Rate']  
  
    h2h_player_1_win_rate = h2h_player_1_win_rate.iloc[0] if not h2h_player_1_win_rate.empty else 0  
    h2h_player_2_win_rate = h2h_player_2_win_rate.iloc[0] if not h2h_player_2_win_rate.empty else 0  
  
    player_1_probability, player_2_probability = estimate_probability(player_1_win_rate, player_2_win_rate, h2h_player_1_win_rate, h2h_player_2_win_rate, performance_weight, h2h_weight)  
    max_odd_1 = data['Odd_1'].max()  
    max_odd_2 = data['Odd_2'].max()  
      
    if player_1_probability == 0:  
        updated_odd_1 = max_odd_1  
    else:  
        updated_odd_1 = 1 / player_1_probability  
      
    if player_2_probability == 0:  
        updated_odd_2 = max_odd_2  
    else:  
        updated_odd_2 = 1 / player_2_probability  
  
    return updated_odd_1, updated_odd_2  
'''

[USER (data scientist)]: Finally, I'd like to loop through all the matches and update the odds for each one. Can you help me with that? Please calculate the head-to-head win rates for players in the ATP tennis dataset and use these rates, along with individual performance metrics, to update the odds for matches involving a specific player. Then, generate and display a DataFrame containing the original and updated odds for these matches.

[YOU (AI assistant)]: You got it! Here's some code that loops through the matches, updates the odds, and stores the results in a DataFrame :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

# Calculate head-to-head win rates  
h2h_win_rates = calculate_head_to_head_win_rate(atp_tennis)  
print(h2h_win_rates)
  
# Initialize an empty DataFrame for storing the results  
updated_odds_df = pd.DataFrame(columns=['Match ID', 'Original Odd_1', 'Original Odd_2', 'Updated Odd_1', 'Updated Odd_2'])  

# Loop through the affected matches  
for match_id in federer_match_ids:  
    # Update the odds for the match  
    updated_odd_1, updated_odd_2 = update_odds(match_id, 0.7, 0.3, atp_tennis, h2h_win_rates)  
  
    # Append the results to the DataFrame  
    original_odd_1 = atp_tennis.loc[match_id, 'Odd_1']  
    original_odd_2 = atp_tennis.loc[match_id, 'Odd_2']  
    updated_odds_df = pd.concat([updated_odds_df, pd.DataFrame({'Match ID': [match_id], 'Original Odd_1': [original_odd_1], 'Original Odd_2': [original_odd_2], 'Updated Odd_1': [updated_odd_1], 'Updated Odd_2': [updated_odd_2]})], ignore_index=True)  

# Display the resulting DataFrame  
print(updated_odds_df)

'''

[USER (data scientist)]: Hey there! I've got this dataset with original and updated odds for some matches, and I wanna take a closer look at the differences between them. Can you lend me a hand? Please note that the original odds are in 'Original Odd_1' and 'Original Odd_2', and the updated odds are in 'Updated Odd_1' and 'Updated Odd_2' Please generate and display a DataFrame that calculates the differences between the original and updated odds for players in the ATP tennis dataset.

[YOU (AI assistant)]: Awesome! Let's whip up two new columns in your dataframe to store the differences between the original and updated odds. Here's the code you'll need :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

updated_odds_df['Difference Odd_1'] = updated_odds_df['Updated Odd_1'] - updated_odds_df['Original Odd_1']   
updated_odds_df['Difference Odd_2'] = updated_odds_df['Updated Odd_2'] - updated_odds_df['Original Odd_2']  

print(updated_odds_df)

'''

[USER (data scientist)]: Sweet! Now, I wanna see the percentage change for each of these differences. How do I go about that? Please generate and display a DataFrame that calculates the percentage change between the original and updated odds for players in the ATP tennis dataset.

[YOU (AI assistant)]: No problem! To get the percentage change, just divide the difference by the original odd and multiply by 100. Let's add two more columns to the dataframe for the percentage change of each odd. Here's the code for that :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

updated_odds_df['Percentage Change Odd_1'] = (updated_odds_df['Difference Odd_1'] / updated_odds_df['Original Odd_1']) * 100   
updated_odds_df['Percentage Change Odd_2'] = (updated_odds_df['Difference Odd_2'] / updated_odds_df['Original Odd_2']) * 100   

print(updated_odds_df)

'''

[USER (data scientist)]: That's exactly what I was looking for! Lastly, how do I show the dataframe with all these comparison metrics? Please display the DataFrame 'updated_odds_df' from the ATP tennis dataset.

[YOU (AI assistant)]: Easy peasy! Just use this code to display the updated dataframe with all the new columns :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv('atp_tennis.csv')

updated_odds_df 

print(updated_odds_df)

'''

[USER (data scientist)]: Cool! So, first I want to focus on the quarterfinals, semifinals, and finals. Please note that my dataset atp_tennis has a 'Round' column. Please generate and display a DataFrame containing matches from the quarterfinals, semifinals, and finals rounds in the ATP tennis dataset.

[YOU (AI assistant)]: No problem! Here's the code to filter the dataset for those rounds :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv("atp_tennis.csv")

later_rounds = atp_tennis[atp_tennis['Round'].isin(['Quarterfinals', 'Semifinals', 'Finals'])] 

print(later_rounds)

'''

[USER (data scientist)]: Great! Now, I've got another dataframe updated_odds_df with updated odds for each match. Please note that it has 'Match ID', 'Updated Odd_1', and 'Updated Odd_2' columns. Can we merge it with the original dataset? Please generate and display a DataFrame that merges matches from the later rounds (quarterfinals, semifinals, finals) with the updated odds data in the ATP tennis dataset.

[YOU (AI assistant)]: Sure thing! Here's the code to merge the datasets using the 'Match ID' column :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv("atp_tennis.csv")

later_rounds_odds = later_rounds.merge(updated_odds_df[['Match ID', 'Updated Odd_1', 'Updated Odd_2']], left_index=True, right_on='Match ID') 

print(later_rounds_odds)

'''

[USER (data scientist)]: Awesome! Now, let's figure out the original and updated match favorites based on the odds. And let's say the player with lower odds is more likely to win. Please generate and display a DataFrame that includes the identification of original and updated match favorites based on odds for later round matches in the ATP tennis dataset.

[YOU (AI assistant)]: Got it! Here's the code to calculate the original and updated match favorites :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv("atp_tennis.csv")

later_rounds_odds['Original Favorite'] = later_rounds_odds.apply(lambda row: row['Player_1'] if row['Odd_1'] < row['Odd_2'] else row['Player_2'], axis=1)   
later_rounds_odds['Updated Favorite'] = later_rounds_odds.apply(lambda row: row['Player_1'] if row['Updated Odd_1'] < row['Updated Odd_2'] else row['Player_2'], axis=1)   

print(later_rounds_odds)

'''

[USER (data scientist)]: Sweet! Now, let's see if there are any changes in match favorites and shifts in tournament dynamics based on the updated odds. Please generate and display a DataFrame that evaluates changes in match favorites and the overall shift in tournament dynamics for later round matches in the ATP tennis dataset.

[YOU (AI assistant)]: You got it! Here's the code to calculate the changes in match favorites and shifts in tournament dynamics :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv("atp_tennis.csv")

later_rounds_odds['Change in Favorite'] = later_rounds_odds['Original Favorite'] != later_rounds_odds['Updated Favorite']   
later_rounds_odds['Shift in Tournament Dynamics'] = later_rounds_odds['Change in Favorite'].sum() 

print(later_rounds_odds)

'''

[USER (data scientist)]: Perfect! Lastly, I want to create a dataframe with all the info I need to analyze the impact. Please generate and display a DataFrame that includes selected columns such as Match ID, Round, Original and Updated Odds, Favorites, and changes in tournament dynamics for later round matches in the ATP tennis dataset.

[YOU (AI assistant)]: Sure thing! Here's the code to create a dataframe with all the necessary columns :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv("atp_tennis.csv")

impact_df = later_rounds_odds[['Match ID', 'Round', 'Odd_1', 'Odd_2', 'Updated Odd_1', 'Updated Odd_2', 'Original Favorite', 'Updated Favorite', 'Change in Favorite', 'Shift in Tournament Dynamics']]  

print(impact_df)

'''

[USER (data scientist)]: Hey, I've got this dataset with original and updated odds for two players in a tournament. I want to see how the competitiveness of the tournament changes with the updated odds. Can you help me out? 

[YOU (AI assistant)]: Absolutely! Let's break it down step by step. First, we need to find the difference in odds for each match. Is your dataset in a pandas DataFrame? 

[USER (data scientist)]: Yep, it's in a DataFrame called updated_odds_df. Please generate and display a DataFrame that calculates the differences between the original and updated odds for two sets of data in the ATP tennis dataset.

[YOU (AI assistant)]: Cool! Let's calculate the difference in odds for each match. Here's the code. Now that we've got the difference in odds, let's visualize the data. What kind of plot would you like to see for the distribution of original and updated odds for both players? :
'''
import pandas as pd
import numpy as np
import pickle

atp_tennis = pd.read_csv("atp_tennis.csv")

updated_odds_df['Difference Odd_1'] = updated_odds_df['Updated Odd_1'] - updated_odds_df['Original Odd_1']   
updated_odds_df['Difference Odd_2'] = updated_odds_df['Updated Odd_2'] - updated_odds_df['Original Odd_2']   

print(updated_odds_df)

'''

[USER (data scientist)]: How about a density plot? Please generate and display KDE plots comparing the distribution of original and updated odds for Player 1 and Player 2 in the ATP tennis dataset.

[YOU (AI assistant)]: Sure thing! You can use seaborn's kdeplot to create density plots. Here's the code. These plots show the distribution of original and updated odds for both players. What else would you like to check out? :
'''
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

atp_tennis = pd.read_csv("atp_tennis.csv")

plt.figure(figsize=(12, 6))   
sns.kdeplot(updated_odds_df['Original Odd_1'], label='Original Odd_1', fill=True)   
sns.kdeplot(updated_odds_df['Updated Odd_1'], label='Updated Odd_1', fill=True)   
plt.xlabel('Odds')   
plt.ylabel('Density')   
plt.title('Distribution of Original and Updated Odds for Player 1')   
plt.legend()   
plt.savefig('./updated_odds_change_for_player_1.png')
plt.show()

plt.figure(figsize=(12, 6))   
sns.kdeplot(updated_odds_df['Original Odd_2'], label='Original Odd_2', fill=True)   
sns.kdeplot(updated_odds_df['Updated Odd_2'], label='Updated Odd_2', fill=True)   
plt.xlabel('Odds')   
plt.ylabel('Density')   
plt.title('Distribution of Original and Updated Odds for Player 2')   
plt.legend()   
plt.savefig('./ref_result/updated_odds_change_for_player_2.png')
plt.show()   
'''

[USER (data scientist)]: I want to see how match favorites change with the updated odds. Please note that there's a column called 'Change in Favorite' in my 'later_rounds_odds' DataFrame. Please generate and display a count plot visualizing changes in match favorites based on updated odds in the ATP tennis dataset.

[YOU (AI assistant)]: Awesome! Let's use seaborn's 'countplot' to visualize the changes in match favorites. Here's the code. Now you can see how match favorites change with the updated odds. Anything else you'd like to analyze? :
'''
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

atp_tennis = pd.read_csv("atp_tennis.csv")

# Plot the changes in match favorites
plt.figure(figsize=(12, 6))
sns.countplot(x='Change in Favorite', data=later_rounds_odds)
plt.xlabel('Change in Match Favorite')
plt.ylabel('Count')
plt.title('Changes in Match Favorites Based on Updated Odds')
plt.savefig('./ref_result/changes_in_match_favorites.png')
plt.show()
'''

[USER (data scientist)]: Lastly, I want to look at the shifts in tournament dynamics based on the updated odds. Please note that there's a column called 'Shift in Tournament Dynamics' in my 'later_rounds_odds' DataFrame. Please generate and display a line plot visualizing shifts in tournament dynamics based on updated odds in the ATP tennis dataset.

My template of code snippet is:

---BEGIN CODE TEMPLATE---

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

atp_tennis = pd.read_csv("atp_tennis.csv")

# Plot the shifts in tournament dynamics
plt.figure(figsize=(12, 6))

# YOUR SOLUTION BEGIN:
<code1>
[COMPLETE YOUR CODE] 
</code1>
# YOUR SOLUTION END

plt.savefig('./shifts_in_tournament_dynamics.png')
plt.show()

---END CODE TEMPLATE---

Please note that you have to generate the WHOLE python code instead of code segments based on the code snippet using Pandas library 2.0.3 version and Matplotlib library 3.7.4 version. You must keep all comments in code snippet unchanged.

[YOU (AI assistant)]: Great! Let's use seaborn's 'lineplot' to visualize the shifts in tournament dynamics. Here's the code: 
'''
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

atp_tennis = pd.read_csv("atp_tennis.csv")

# Plot the shifts in tournament dynamics
plt.figure(figsize=(12, 6))

# YOUR SOLUTION BEGIN:
